package com.ljk.encrypt;

import com.ljk.encrypt.constant.ProviderServiceTypeEnum;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.ArrayList;
import java.util.List;

/**
 * 加密工具类
 *
 * @author ljk
 * @since 2024/6/17 9:00
 */
public class EncryptUtil {

    private EncryptUtil() {
        // 禁止实例化
    }

    /**
     * 列出当前Java环境中所有支持的 MessageDigest 算法。
     *
     * @return 包含所有支持的MessageDigest算法名称的列表
     */
    public static List<String> listMessageDigest() {
        return listProviderService(ProviderServiceTypeEnum.MessageDigest);
    }

    public static List<String> listProviderService(ProviderServiceTypeEnum typeEnum) {
        List<String> list = new ArrayList<>();
        for (Provider provider : Security.getProviders()) {
            for (Provider.Service service : provider.getServices()) {
                if (service.getType().equals(typeEnum.toString())) {
                    list.add(service.getAlgorithm());
                }
            }
        }
        return list;
    }

    /**
     * 通用加密方法,可使用多种加密方式,具体要看jdk提供商支持的方式
     *
     * @param input 待加密字符串
     * @return 加密后的字符串
     * @see com.ljk.encrypt.EncryptUtil.listEncryptType()
     */
    public static String encrypt(String input, String encryptType) {
        if (encryptType == null) {
            return null;
        }
        try {
            MessageDigest md = MessageDigest.getInstance(encryptType.toUpperCase());
            return bytesToHex(md.digest(input.getBytes(StandardCharsets.UTF_8)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(encryptType + " encrypt fail", e);
        }
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

}
